社交媒体应用开发教程

1. React 简介和特性

1.1 React 是什么?

React 是一个用于构建用户界面的 JavaScript 库。它由 Facebook 开发,以其高效的组件化设计和虚拟 DOM 技术而闻名。

1.2 React 的主要特性

  • 组件化:React 应用由多个组件构成,每个组件负责一部分 UI。
  • 虚拟 DOM:React 使用虚拟 DOM 来优化 DOM 操作,提高性能。
  • 单向数据流:数据只能从父组件流向子组件,确保数据流清晰。

2. 环境搭建

2.1 安装 Node.js 和 npm

首先,确保你已经安装了 Node.js 和 npm。你可以通过以下命令检查是否安装成功:

node -v
npm -v

2.2 使用 Create React App 创建项目

Create React App 是一个官方推荐的工具,用于快速搭建 React 项目。

npx create-react-app social-media-app
cd social-media-app
npm start

3. JSX 语法

3.1 什么是 JSX?

JSX 是一种 JavaScript 的语法扩展,允许你在 JavaScript 代码中编写类似 HTML 的代码。

3.2 JSX 示例

const element = <h1>Hello, world!</h1>;

4. 组件基础

4.1 函数组件

函数组件是一个简单的 JavaScript 函数,返回 JSX。

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

4.2 类组件

类组件是一个继承自 React.Component 的 JavaScript 类。

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

5. Props 和 State

5.1 Props

Props 是组件的输入参数,用于从父组件向子组件传递数据。

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

5.2 State

State 是组件内部的状态,用于管理组件的动态数据。

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = { date: new Date() };
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

6. 生命周期方法

6.1 常用生命周期方法

  • componentDidMount:组件挂载后调用。
  • componentDidUpdate:组件更新后调用。
  • componentWillUnmount:组件卸载前调用。
class Clock extends React.Component {
  componentDidMount() {
    this.timerID = setInterval(() => this.tick(), 1000);
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

7. 事件处理

7.1 事件处理示例

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isToggleOn: true };

    // 为了在回调中使用 `this`,这个绑定是必不可少的
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }

  render() {
    return (
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
    );
  }
}

8. 条件渲染

8.1 条件渲染示例

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

9. 列表和 Keys

9.1 列表渲染示例

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
);

10. 表单处理

10.1 受控组件示例

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: '' };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({ value: event.target.value });
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

11. 组合 vs 继承

11.1 组合示例

function Dialog(props) {
  return (
    <FancyBorder color="blue">
      <h1 className="Dialog-title">
        {props.title}
      </h1>
      <p className="Dialog-message">
        {props.message}
      </p>
    </FancyBorder>
  );
}

12. 高阶组件 (HOC)

12.1 HOC 示例

function withSubscription(WrappedComponent, selectData) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        data: selectData(DataSource, props)
      };
    }

    render() {
      return <WrappedComponent data={this.state.data} {...this.props} />;
    }
  };
}

13. Render Props

13.1 Render Props 示例

class MouseTracker extends React.Component {
  render() {
    return (
      <div>
        <h1>Move the mouse around!</h1>
        <Mouse render={mouse => (
          <Cat mouse={mouse} />
        )}/>
      </div>
    );
  }
}

14. Context API

14.1 Context API 示例

const ThemeContext = React.createContext('light');

class App extends React.Component {
  render() {
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

15. Refs 和 DOM

15.1 Refs 示例

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.textInput = React.createRef();
  }

  focusTextInput() {
    this.textInput.current.focus();
  }

  render() {
    return (
      <div>
        <input
          type="text"
          ref={this.textInput} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focusTextInput.bind(this)}
        />
      </div>
    );
  }
}

16. useState 和 useEffect

16.1 Hooks 示例

import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

17. useContext

17.1 useContext 示例

const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee"
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222"
  }
};

const ThemeContext = React.createContext(themes.light);

function App() {
  return (
    <ThemeContext.Provider value={themes.dark}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

function Toolbar(props) {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return (
    <button style={{ background: theme.background, color: theme.foreground }}>
      I am styled by theme context!
    </button>
  );
}

18. useReducer

18.1 useReducer 示例

const initialState = {count: 0};

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return {count: state.count + 1};
    case 'decrement':
      return {count: state.count - 1};
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({type: 'decrement'})}>-</button>
      <button onClick={() => dispatch({type: 'increment'})}>+</button>
    </>
  );
}

19. 自定义 Hooks

19.1 自定义 Hook 示例

import { useState, useEffect } from 'react';

function useFriendStatus(friendID) {
  const [isOnline, setIsOnline] = useState(null);

  useEffect(() => {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(friendID, handleStatusChange);
    return () => {
      ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
    };
  });

  return isOnline;
}

20. Hooks 规则和最佳实践

20.1 Hooks 规则

  • 只能在函数组件的顶层调用 Hooks。
  • 只能在 React 函数组件中调用 Hooks。

20.2 最佳实践

  • 使用 useEffect 来处理副作用。
  • 使用 useContext 来共享全局状态。

21. Redux 基础

21.1 Redux 示例

import { createStore } from 'redux';

function counterReducer(state = { value: 0 }, action) {
  switch (action.type) {
    case 'counter/incremented':
      return { value: state.value + 1 }
    case 'counter/decremented':
      return { value: state.value - 1 }
    default:
      return state
  }
}

let store = createStore(counterReducer)

store.subscribe(() => console.log(store.getState()))

store.dispatch({ type: 'counter/incremented' })
store.dispatch({ type: 'counter/incremented' })
store.dispatch({ type: 'counter/decremented' })

22. Redux Toolkit

22.1 Redux Toolkit 示例

import { createSlice, configureStore } from '@reduxjs/toolkit';

const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    value: 0
  },
  reducers: {
    incremented: state => {
      state.value += 1;
    },
    decremented: state => {
      state.value -= 1;
    }
  }
});

const store = configureStore({
  reducer: counterSlice.reducer
});

store.subscribe(() => console.log(store.getState()));

store.dispatch(counterSlice.actions.incremented());
store.dispatch(counterSlice.actions.incremented());
store.dispatch(counterSlice.actions.decremented());

23. MobX 简介

23.1 MobX 示例

import { observable, action, makeObservable } from 'mobx';
import { observer } from 'mobx-react';

class Counter {
  count = 0;

  constructor() {
    makeObservable(this, {
      count: observable,
      increment: action,
      decrement: action
    });
  }

  increment() {
    this.count += 1;
  }

  decrement() {
    this.count -= 1;
  }
}

const counter = new Counter();

const CounterView = observer(({ counter }) => (
  <div>
    <p>{counter.count}</p>
    <button onClick={() => counter.increment()}>+</button>
    <button onClick={() => counter.decrement()}>-</button>
  </div>
));

function App() {
  return <CounterView counter={counter} />;
}

24. Recoil 入门

24.1 Recoil 示例

import React from 'react';
import { RecoilRoot, atom, useRecoilState } from 'recoil';

const counterState = atom({
  key: 'counterState',
  default: 0,
});

function Counter() {
  const [count, setCount] = useRecoilState(counterState);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>-</button>
    </div>
  );
}

function App() {
  return (
    <RecoilRoot>
      <Counter />
    </RecoilRoot>
  );
}

25. 状态管理最佳实践

25.1 最佳实践

  • 使用 Redux 或 Context API 来管理全局状态。
  • 避免在组件中直接修改状态,使用 reducers 或 actions。

26. React Router 基础

26.1 React Router 示例

import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

function App() {
  return (
    <Router>
      <Switch>
        <Route path="/about">
          <About />
        </Route>
        <Route path="/users">
          <Users />
        </Route>
        <Route path="/">
          <Home />
        </Route>
      </Switch>
    </Router>
  );
}

27. 动态路由

27.1 动态路由示例

<Route path="/users/:id">
  <User />
</Route>

28. 嵌套路由

28.1 嵌套路由示例

function App() {
  return (
    <Router>
      <Switch>
        <Route path